package authvalidator

import (
	"errors"
	"fmt"
	"time"
	"yunj/pkg/global"
	"yunj/pkg/yunj/app/dto"
	"yunj/pkg/yunj/app/enum/admin/authenum"
	"yunj/pkg/yunj/app/model"
	"yunj/pkg/yunj/core/builder"
	"yunj/pkg/yunj/util"

	"github.com/worklz/go-validate"
)

type Auth struct {
	validate.Validator
}

func (v *Auth) HandleDatas(datas map[string]interface{}, scene string) (err error) {
	if scene == "FormSubmit" {
		err = v.HandleDatasByFormSubmit(datas)
		if err != nil {
			return
		}
	}
	return
}

func (v *Auth) HandleDatasByFormSubmit(datas map[string]interface{}) (err error) {
	datas = util.MapFloat64ToUints(datas)
	builderRaw, exists := datas["builder"]
	if !exists {
		err = errors.New("builder参数缺失")
		return
	}
	formBuilder, ok := builderRaw.(*builder.Form)
	if !ok {
		err = errors.New("builder参数异常")
		return
	}
	loadAuth, err := builder.FormLoadValue[dto.AdminAuthPageFormLoadResponse](formBuilder)
	if err != nil {
		return
	}
	currTime := time.Now()
	dbAuth := &model.AdminAuth{
		Name:          util.MapKeyValue(datas, "name", ""),
		Desc:          util.MapKeyValue(datas, "desc", ""),
		Type:          util.MapKeyValue(datas, "type", authenum.TYPE_NORMAL),
		Icon:          util.MapKeyValue(datas, "icon", ""),
		RequestMode:   util.MapKeyValue(datas, "request_mode", authenum.REQUEST_MODE_NIL),
		PageOpen:      util.MapKeyValue(datas, "page_open", authenum.PAGE_OPEN_NIL),
		RequestUrl:    model.RequestUrl(util.MapKeyValue(datas, "request_url", "")),
		RequestMethod: util.MapKeyValue(datas, "request_method", authenum.REQUEST_METHOD_ANY),
		UpdatedAt:     &currTime,
	}
	// 处理提交参数request_require_params
	originLocation := v.handleDatasByFormSubmitRequestRequireParams(datas, dbAuth)
	// parent_key
	isAddChild := util.MapKeyValue(datas, "is_add_child", uint8(0)) == 1
	if isAddChild {
		dbAuth.ParentKey = loadAuth.ParentKey
	} else {
		dbAuth.ParentKey = util.MapKeyValue(datas, "parent_key", "")
	}
	// 新增/编辑
	isEdit := util.MapKeyValue(datas, "is_edit", uint8(0)) == 1
	existsAuthKeyMap := map[string]struct{}{}
	if isEdit {
		if loadAuth.Key == "" {
			return errors.New("数据异常，请刷新页面后重试！")
		}
		// 编辑
		dbAuth.Key = loadAuth.Key
		dbAuth.ParentKey = util.MapKeyValue(datas, "parent_key", "")
	} else {
		// 新增
		// 判断key是否存在
		key := util.MapKeyValue(datas, "key", "")
		if key == "" {
			return errors.New("KEY不能为空！")
		}
		var existsAuthKeys []string
		if err = global.MySQL.Model(&model.AdminAuth{}).Where("`key` like ?", key+"%").Pluck("key", &existsAuthKeys).Error; err != nil {
			return fmt.Errorf("数据查询异常！%v", err)
		}
		for _, v := range existsAuthKeys {
			existsAuthKeyMap[v] = struct{}{}
		}
		if _, exists := existsAuthKeyMap[key]; exists {
			return fmt.Errorf("KEY=%v已存在！", key)
		}
		dbAuth.Key = key
		dbAuth.CreatedAt = &currTime
	}
	datas["dbAuth"] = dbAuth
	// fmt.Printf("111|%v|%T\r\n", dbChildAuths, dbChildAuths)
	// err = fmt.Errorf("测试中...")
	// 创建子权限
	if !isEdit {
		dbChildAuths, err := v.getFormSubmitCreateChildAuths(datas, dbAuth, existsAuthKeyMap, originLocation, &currTime)
		if err != nil {
			return err
		}
		datas["dbChildAuths"] = dbChildAuths
	}
	return
}

// 获取表单提交，要创建的子权限
func (v *Auth) getFormSubmitCreateChildAuths(datas map[string]interface{}, dbAuth *model.AdminAuth, existsAuthKeyMap map[string]struct{}, originLocation uint8, currTime *time.Time) (dbChildAuths []*model.AdminAuth, err error) {
	createChildAuths := util.MapKeyValue(datas, "create_child_auths", []any{})
	dbChildAuths = []*model.AdminAuth{}
	for _, v := range createChildAuths {
		vv, ok := authenum.ChildAuthNodeEnum.IsValue(v)
		if !ok {
			err = fmt.Errorf("添加子权限节点数据异常，请刷新页面后重试！")
			return
		}
		node := authenum.ChildAuthNodeByValue(vv)
		nodeAuthKey := dbAuth.Key + "_" + node.Value
		if _, exists := existsAuthKeyMap[nodeAuthKey]; exists {
			err = fmt.Errorf("创建子权限异常！KEY=%v已存在！", nodeAuthKey)
			return
		}
		dbChildAuth := &model.AdminAuth{
			Key:         nodeAuthKey,
			ParentKey:   node.GetAuthParentKey(dbAuth.Key),
			Name:        node.GetDesc(),
			Type:        authenum.TYPE_NORMAL,
			RequestMode: node.GetAuthRequestMode(),
			PageOpen:    node.GetAuthPageOpen(),
			Sort:        node.GetAuthSort(),
			CreatedAt:   currTime,
			UpdatedAt:   currTime,
		}
		if dbChildAuth.RequestMode == authenum.REQUEST_MODE_INTERNAL_ROUTER {
			if dbAuth.RequestUrl != "" {
				dbChildAuth.RequestUrl = model.RequestUrl(node.GetAuthRequestUrl(string(dbAuth.RequestUrl)))
			}
			if dbChildAuth.RequestUrl != "" {
				dbChildAuth.RequestMethod = node.GetAuthRequestMethod()
				dbChildAuth.RequestRequireParams = node.GetAuthRequestRequireParams(originLocation)
			}
		}
		dbChildAuths = append(dbChildAuths, dbChildAuth)
	}
	return
}

// 处理提交参数request_require_params
func (v *Auth) handleDatasByFormSubmitRequestRequireParams(datas map[string]interface{}, dbAuth *model.AdminAuth) (originLocation uint8) {
	// request_require_params
	if requestRequireParams, exists := datas["request_require_params"]; exists {
		dbAuth.RequestRequireParams.Scan(requestRequireParams)
	}
	// request_require_params.originLocation
	if authenum.IsMenuType(dbAuth.Type) {
		originLocation = dbAuth.Type
		// 判断是否配置有originLocation
		var isConfigOriginLocation bool
		for _, v := range dbAuth.RequestRequireParams {
			if keyRaw, exists := v["key"]; exists {
				if key, ok := keyRaw.(string); ok && key == "originLocation" {
					if valueRaw, exists := v["value"]; exists {
						originLocation, _ = util.ToUint8(valueRaw)
						isConfigOriginLocation = true
						break
					}
				}
			}
		}
		if !isConfigOriginLocation {
			dbAuth.RequestRequireParams = append(dbAuth.RequestRequireParams, map[string]any{
				"key":   "originLocation",
				"value": originLocation,
			})
		}
	}
	return
}
